<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>2.1.1. Data Consumers &mdash; Pyslet 0.4.20140526 documentation</title>
    
    <link rel="stylesheet" href="_static/default.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '0.4.20140526',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Pyslet 0.4.20140526 documentation" href="index.html" />
    <link rel="up" title="2.1. The Open Data Protocol (OData)" href="odatav2.html" />
    <link rel="next" title="2.1.2. OData Providers" href="odatav2_provider.html" />
    <link rel="prev" title="2.1. The Open Data Protocol (OData)" href="odatav2.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="odatav2_provider.html" title="2.1.2. OData Providers"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="odatav2.html" title="2.1. The Open Data Protocol (OData)"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Pyslet 0.4.20140526 documentation</a> &raquo;</li>
          <li><a href="general.html" >2. Supporting Standards</a> &raquo;</li>
          <li><a href="odatav2.html" accesskey="U">2.1. The Open Data Protocol (OData)</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="data-consumers">
<h1>2.1.1. Data Consumers<a class="headerlink" href="#data-consumers" title="Permalink to this headline">¶</a></h1>
<p>Warning: the OData client doesn&#8217;t support certificate validation when
accessing servers through https URLs.  This feature is coming soon...</p>
<div class="toctree-wrapper compound">
<ul class="simple">
</ul>
</div>
<div class="section" id="introduction">
<h2>2.1.1.1. Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline">¶</a></h2>
<p>Let&#8217;s start with a simple illustration of how to consume data using the
DAL API by walking through the use of the OData client.</p>
<p>The client implementation uses Python&#8217;s logging module to provide
logging, when learning about the client it may help to turn logging up
to &#8220;INFO&#8221; as it makes it clearer what the client is doing.  &#8220;DEBUG&#8221;
would show exactly what is passing over the wire.:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">logging</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
</pre></div>
</div>
<p>To create a new client simply instantiate a Client object.  You can pass
the URL of the service root you wish to connect to directly to the
constructor which will then call the service to download the list of
feeds and the metadata document from which it will set the
<tt class="xref py py-attr docutils literal"><span class="pre">Client.model</span></tt>.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pyslet.odata2.client</span> <span class="kn">import</span> <span class="n">Client</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">=</span><span class="n">Client</span><span class="p">(</span><span class="s">&quot;http://services.odata.org/V2/Northwind/Northwind.svc/&quot;</span><span class="p">)</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/ HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/$metadata HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>The <tt class="xref py py-attr docutils literal"><span class="pre">Client.feeds</span></tt> attribute is a dictionary mapping the
exposed feeds (by name) onto <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet" title="pyslet.odata2.csdl.EntitySet"><tt class="xref py py-class docutils literal"><span class="pre">EntitySet</span></tt></a>
instances.  This makes it easy to open the feeds as EDM collections.  In
your code you&#8217;d typically use the with statement when opening the
collection but for clarity we&#8217;ll continue on the python command line:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">=</span><span class="n">c</span><span class="o">.</span><span class="n">feeds</span><span class="p">[</span><span class="s">&#39;Products&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">OpenCollection</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="p">:</span> <span class="k">print</span> <span class="n">p</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">1</span>
<span class="go">2</span>
<span class="go">3</span>
<span class="gp">... </span><span class="p">[</span><span class="ow">and</span> <span class="n">so</span> <span class="n">on</span><span class="p">]</span>
<span class="gp">...</span>
<span class="go">20</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$skiptoken=20 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">21</span>
<span class="go">22</span>
<span class="go">23</span>
<span class="gp">... </span><span class="p">[</span><span class="ow">and</span> <span class="n">so</span> <span class="n">on</span><span class="p">]</span>
<span class="gp">...</span>
<span class="go">76</span>
<span class="go">77</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>Note that products behaves like a dictionary, iterating through it
iterates through the keys in the dictionary.  In this case these are the
keys of the entities in the collection of products.  Notice that the
client logs several requests to the server interspersed with the printed
output.  Subsequent requests use $skiptoken because the server is
limiting the maximum page size.  These calls are made as you iterate
through the collection allowing you to iterate through very large
collections.</p>
<p>The keys alone are of limited interest, let&#8217;s try a similar loop but this
time we&#8217;ll print the product names as well:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">1 Chai</span>
<span class="go">2 Chang</span>
<span class="go">3 Aniseed Syrup</span>
<span class="gp">...</span>
<span class="gp">...</span>
<span class="go">20 Sir Rodney&#39;s Marmalade</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$skiptoken=20 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">21 Sir Rodney&#39;s Scones</span>
<span class="go">22 Gustaf&#39;s Knäckebröd</span>
<span class="go">23 Tunnbröd</span>
<span class="gp">...</span>
<span class="gp">...</span>
<span class="go">76 Lakkalikööri</span>
<span class="go">77 Original Frankfurter grüne Soße</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>Sir Rodney&#8217;s Scones sound interesting, we can grab an individual record
in the usual way:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">scones</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21) HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">scones</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">ProductID 21</span>
<span class="go">ProductName Sir Rodney&#39;s Scones</span>
<span class="go">SupplierID 8</span>
<span class="go">CategoryID 3</span>
<span class="go">QuantityPerUnit 24 pkgs. x 4 pieces</span>
<span class="go">UnitPrice 10.0000</span>
<span class="go">UnitsInStock 3</span>
<span class="go">UnitsOnOrder 40</span>
<span class="go">ReorderLevel 5</span>
<span class="go">Discontinued False</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>Well, I&#8217;ve simply got to have some of these, let&#8217;s use one of the navigation
properties to load information about the supplier:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">supplier</span><span class="o">=</span><span class="n">scones</span><span class="p">[</span><span class="s">&#39;Supplier&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">GetEntity</span><span class="p">()</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)/Supplier HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">supplier</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">SupplierID 8</span>
<span class="go">CompanyName Specialty Biscuits, Ltd.</span>
<span class="go">ContactName Peter Wilson</span>
<span class="go">ContactTitle Sales Representative</span>
<span class="go">Address 29 King&#39;s Way</span>
<span class="go">City Manchester</span>
<span class="go">Region None</span>
<span class="go">PostalCode M14 GSD</span>
<span class="go">Country UK</span>
<span class="go">Phone (161) 555-4448</span>
<span class="go">Fax None</span>
<span class="go">HomePage None</span>
</pre></div>
</div>
<p>Attempting to load a non existent entity results in a KeyError of
course:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">p</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">211</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(211) HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 404</span>
<span class="gt">Traceback (most recent call last):</span>
  File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">&lt;module&gt;</span>
  File <span class="nb">&quot;/Library/Python/2.7/site-packages/pyslet/odata2/client.py&quot;</span>, line <span class="m">165</span>, in <span class="n">__getitem__</span>
        <span class="k">raise</span> <span class="ne">KeyError</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="gr">KeyError</span>: <span class="n">211</span>
</pre></div>
</div>
<p>Finally, when we&#8217;re done, it is a good idea to close the open
collection:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="the-data-access-layer-in-depth">
<h2>2.1.1.2. The Data Access Layer in Depth<a class="headerlink" href="#the-data-access-layer-in-depth" title="Permalink to this headline">¶</a></h2>
<p>In the introduction we created an OData Client object using a URL, but
in general the way you connect to a data service will vary depending on
the implementation.  The Client class itself isn&#8217;t actually part of the
DAL API itself.</p>
<p>The API starts with a model of the <em>data service</em>.  The model is
typically parsed from an XML file. For the OData client the XML file is
obtained from the service&#8217;s $metadata URL.  Here&#8217;s an extract from the
Northwind $metadata file showing the definition of the data service,
I&#8217;ve removed the XML namespace definitions for brevity:</p>
<div class="highlight-python"><div class="highlight"><pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; standalone=&quot;yes&quot;?&gt;
&lt;edmx:Edmx Version=&quot;1.0&quot;&gt;
        &lt;edmx:DataServices m:DataServiceVersion=&quot;1.0&quot;&gt;
        &lt;Schema Namespace=&quot;NorthwindModel&quot;&gt;
                &lt;EntityType Name=&quot;Category&quot;&gt;
                        &lt;!-- rest of the definitions go here... --&gt;
</pre></div>
</div>
<p>Each element is represented by an object in Pyslet, the starting point
for the API is the <tt class="xref py py-class docutils literal"><span class="pre">DataServices</span></tt> object.
A DataServices object can contain multiple
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Schema" title="pyslet.odata2.csdl.Schema"><tt class="xref py py-class docutils literal"><span class="pre">Schema</span></tt></a> elements, which in turn can
contain multiple <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityContainer" title="pyslet.odata2.csdl.EntityContainer"><tt class="xref py py-class docutils literal"><span class="pre">EntityContainer</span></tt></a>
elements which in turn can contain multiple
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet" title="pyslet.odata2.csdl.EntitySet"><tt class="xref py py-class docutils literal"><span class="pre">EntitySet</span></tt></a> elements.  The following
diagram illustrates these relationships and compares them with
approximate equivalent concepts in a typical SQL-scenario.</p>
<img alt="_images/dataservices.png" src="_images/dataservices.png" />
<p>In the OData client example we used a short-cut to get to the EntitySet
objects we were interested in by using the feeds property of the client
itself.  However, we could have used the model directly as follows,
continuing with the same session:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span>
<span class="go">&lt;pyslet.odata2.metadata.Edmx object at 0x10140a9d0&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span>
<span class="go">&lt;pyslet.odata2.metadata.DataServices object at 0x107fdb990&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="o">.</span><span class="n">Schema</span><span class="p">:</span> <span class="k">print</span> <span class="n">s</span><span class="o">.</span><span class="n">name</span>
<span class="gp">...</span>
<span class="go">NorthwindModel</span>
<span class="go">ODataWeb.Northwind.Model</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="p">[</span><span class="s">&#39;ODataWeb.Northwind.Model&#39;</span><span class="p">]</span>
<span class="go">&lt;pyslet.odata2.csdl.Schema object at 0x10800cd90&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="p">[</span><span class="s">&#39;ODataWeb.Northwind.Model&#39;</span><span class="p">][</span><span class="s">&#39;NorthwindEntities&#39;</span><span class="p">]</span>
<span class="go">&lt;pyslet.odata2.metadata.EntityContainer object at 0x10800cdd0&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="p">[</span><span class="s">&#39;ODataWeb.Northwind.Model&#39;</span><span class="p">][</span><span class="s">&#39;NorthwindEntities&#39;</span><span class="p">][</span><span class="s">&#39;Products&#39;</span><span class="p">]</span>
<span class="go">&lt;pyslet.odata2.metadata.EntitySet object at 0x10800f150&gt;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">feeds</span><span class="p">[</span><span class="s">&#39;Products&#39;</span><span class="p">]</span>
<span class="go">&lt;pyslet.odata2.metadata.EntitySet object at 0x10800f150&gt;</span>
</pre></div>
</div>
<p>As you can see, the same EntitySet object can be obtained by looking it
up in the parent container which behaves like a dictionary, this in turn
can be looked up in the parent Schema which in turn can be looked up in
the DataServices enclosing object.  Elements of the model also support
deep references using dot-concatenation of names which makes the code
easier to read:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="p">[</span><span class="s">&#39;ODataWeb.Northwind.Model&#39;</span><span class="p">][</span><span class="s">&#39;NorthwindEntities&#39;</span><span class="p">][</span><span class="s">&#39;Products&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">GetFQName</span><span class="p">()</span>
<span class="go">ODataWeb.Northwind.Model.NorthwindEntities.Products</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">c</span><span class="o">.</span><span class="n">model</span><span class="o">.</span><span class="n">DataServices</span><span class="p">[</span><span class="s">&#39;ODataWeb.Northwind.Model.NorthwindEntities.Products&#39;</span><span class="p">]</span>
<span class="go">&lt;pyslet.odata2.metadata.EntitySet object at 0x10800f150&gt;</span>
</pre></div>
</div>
<p>When writing an application that would normally use a single database
you should pass an EntityCollection object to it as a data source rather
than the DataServices ancestor.  It is best not to pass an
implementation-specific class like the OData Client as that will make
the application dependent on a particular type of data source.</p>
<div class="section" id="entity-sets">
<h3>2.1.1.2.1. Entity Sets<a class="headerlink" href="#entity-sets" title="Permalink to this headline">¶</a></h3>
<p>The following attributes are useful for consumers of the API (and should
be treated as read only)</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.name" title="pyslet.odata2.csdl.EntitySet.name"><tt class="xref py py-attr docutils literal"><span class="pre">name</span></tt></a></dt>
<dd>The name of the entity set</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.entityTypeName" title="pyslet.odata2.csdl.EntitySet.entityTypeName"><tt class="xref py py-attr docutils literal"><span class="pre">entityTypeName</span></tt></a></dt>
<dd>The name of the entity set&#8217;s EntityType</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.entityType" title="pyslet.odata2.csdl.EntitySet.entityType"><tt class="xref py py-attr docutils literal"><span class="pre">entityType</span></tt></a></dt>
<dd>The <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityType" title="pyslet.odata2.csdl.EntityType"><tt class="xref py py-class docutils literal"><span class="pre">EntityType</span></tt></a> object that defines
the properties for entities in this set.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.keys" title="pyslet.odata2.csdl.EntitySet.keys"><tt class="xref py py-attr docutils literal"><span class="pre">keys</span></tt></a></dt>
<dd><p class="first">A list of the names of the keys for this EntitySet.  For example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">products</span><span class="o">.</span><span class="n">keys</span>
<span class="go">[u&#39;ProductID&#39;]</span>
</pre></div>
</div>
<p class="last">For entity types with compound keys this list will contain multiple
items of course.</p>
</dd>
</dl>
<p>The following methods are useful for consumers of the API.</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.GetFQName" title="pyslet.odata2.csdl.EntitySet.GetFQName"><tt class="xref py py-meth docutils literal"><span class="pre">GetFQName()</span></tt></a></dt>
<dd>Returns the fully qualified name of the entity set, suitable for
looking up the entity set in the enclosing DataServices object.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.GetLocation" title="pyslet.odata2.csdl.EntitySet.GetLocation"><tt class="xref py py-meth docutils literal"><span class="pre">GetLocation()</span></tt></a></dt>
<dd><p class="first">Returns a <a class="reference internal" href="rfc2396.html#pyslet.rfc2396.URI" title="pyslet.rfc2396.URI"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.rfc2396.URI</span></tt></a> object that represents
this entity set:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">products</span><span class="o">.</span><span class="n">GetLocation</span><span class="p">()</span>
<span class="go">http://services.odata.org/V2/Northwind/Northwind.svc/Products</span>
</pre></div>
</div>
<p class="last">(If there is no base URL available this will be a relative URI.)</p>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.OpenCollection" title="pyslet.odata2.csdl.EntitySet.OpenCollection"><tt class="xref py py-meth docutils literal"><span class="pre">OpenCollection()</span></tt></a></dt>
<dd>Returns a <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection" title="pyslet.odata2.csdl.EntityCollection"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.odata2.csdl.EntityCollection</span></tt></a> object
that can be used to access the entities in the set.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.NavigationTarget" title="pyslet.odata2.csdl.EntitySet.NavigationTarget"><tt class="xref py py-meth docutils literal"><span class="pre">NavigationTarget()</span></tt></a></dt>
<dd>Returns the target entity set of a named navigation property.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.NavigationMultiplicity" title="pyslet.odata2.csdl.EntitySet.NavigationMultiplicity"><tt class="xref py py-meth docutils literal"><span class="pre">NavigationMultiplicity()</span></tt></a></dt>
<dd><p class="first">Returns a tuple of multiplicity constants for the named navigation
property.  Constants for these values are defined in
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Multiplicity" title="pyslet.odata2.csdl.Multiplicity"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.odata2.csdl.Multiplicity</span></tt></a>, for example:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">pyslet.odata2.csdl</span> <span class="kn">import</span> <span class="n">Multiplicity</span><span class="p">,</span> <span class="n">EncodeMultiplicity</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">Multiplicity</span><span class="o">.</span><span class="n">ZeroToOne</span><span class="p">,</span> <span class="n">Multiplicity</span><span class="o">.</span><span class="n">One</span><span class="p">,</span> <span class="n">Multiplicity</span><span class="o">.</span><span class="n">Many</span>
<span class="go">0 1 2</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">NavigationMultiplicity</span><span class="p">(</span><span class="s">&#39;Supplier&#39;</span><span class="p">)</span>
<span class="go">(2, 0)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">map</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span><span class="n">EncodeMultiplicity</span><span class="p">(</span><span class="n">x</span><span class="p">),</span><span class="n">products</span><span class="o">.</span><span class="n">NavigationMultiplicity</span><span class="p">(</span><span class="s">&#39;Supplier&#39;</span><span class="p">))</span>
<span class="go">[&#39;*&#39;, &#39;0..1&#39;]</span>
</pre></div>
</div>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet.IsEntityCollection" title="pyslet.odata2.csdl.EntitySet.IsEntityCollection"><tt class="xref py py-meth docutils literal"><span class="pre">IsEntityCollection()</span></tt></a></dt>
<dd>Returns True if the named navigation property points to a collection
of entities or a single entity.  In Pyslet, you can treat all
navigation properties as collections.  In the above example the
collection of Supplier entities obtained by following the &#8216;Supplier&#8217;
navigation property of a Product entity will have at most 1 member.</dd>
</dl>
</div>
<div class="section" id="entity-collections">
<h3>2.1.1.2.2. Entity Collections<a class="headerlink" href="#entity-collections" title="Permalink to this headline">¶</a></h3>
<p>To continue with database analogy above, if EntitySets are like SQL
Tables EntityCollections are somewhat like the database cursors that you
use to actually read data - the difference is that EntityCollections can
only read entities from a single EntitySet.</p>
<p>An <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection" title="pyslet.odata2.csdl.EntityCollection"><tt class="xref py py-class docutils literal"><span class="pre">EntityCollection</span></tt></a> may consume physical
resources (like a database connection) and so must be closed with its
<tt class="xref py py-meth docutils literal"><span class="pre">close()</span></tt> method when you&#8217;re done.
They support the context manager protocol to make this easier so you can
use them in with statements to make clean-up easier:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">with</span> <span class="n">c</span><span class="o">.</span><span class="n">feeds</span><span class="p">[</span><span class="s">&#39;Products&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">OpenCollection</span><span class="p">()</span> <span class="k">as</span> <span class="n">products</span><span class="p">:</span>
        <span class="k">if</span> <span class="mi">42</span> <span class="ow">in</span> <span class="n">products</span><span class="p">:</span>
                <span class="k">print</span> <span class="s">&quot;Found it!&quot;</span>
</pre></div>
</div>
<p>The close method is called automatically when the with statement
exits.</p>
<p>Entity collections also behave like a python dictionary of
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity" title="pyslet.odata2.csdl.Entity"><tt class="xref py py-class docutils literal"><span class="pre">Entity</span></tt></a> instances keyed on a value
representing the Entity&#8217;s key property or properties.  The keys are
either single values (as in the above code example) or tuples in the
case of compound keys. The order of the values in the tuple is taken
from the order of the PropertyRef definitions in the model.</p>
<p>There are two ways to obtain an EntityCollection object.  You can open
an entity set directly or you can open a collection by navigating from a
specific entity through a named navigation property.  Although dictionary-like
there are some differences with true dictionaries.</p>
<p>When you have opened a collection from the base entity set the following
rules apply:</p>
<dl class="docutils">
<dt>collection[key]</dt>
<dd>Returns a new <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity" title="pyslet.odata2.csdl.Entity"><tt class="xref py py-class docutils literal"><span class="pre">Entity</span></tt></a> instance by
looking up the <em>key</em> in the collection.  As a result, subsequent
calls will return a different object, but with the same key!</dd>
<dt>collection[key]=newEntity</dt>
<dd>For an existing entity this is essentially a no-operation.  This
form of assignment cannot be used to create a new entity in the
collection because the act of inserting the entity may alter its key
(for example, when the entity set represents a database table with
an auto-generated primary key).  See below for information on how
to create and update entities.</dd>
<dt>del collection[key]</dt>
<dd>In contrast, del will remove an entity from the collection completely.</dd>
</dl>
<p>When an EntityCollection represents a collection of entities obtained by
navigation then these rules are updated as follows:</p>
<dl class="docutils">
<dt>collection[key]</dt>
<dd>Normally returns a new <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity" title="pyslet.odata2.csdl.Entity"><tt class="xref py py-class docutils literal"><span class="pre">Entity</span></tt></a>
instance by looking up the <em>key</em> in the collection but when the
navigation property has been expanded it will return a cached Entity
(so subsequent calls will return the same object without looking
up the key in the data source again).</dd>
<dt>collection[key]=existingEntity</dt>
<dd>Provided that <em>key</em> is the key of <em>existingEntity</em> this will add an
existing entity to this collection, effectively creating a link from
the entity you were navigating from to an existing entity.</dd>
<dt>del collection[key]</dt>
<dd>Removes the entity with <em>key</em> from this collection.  The entity is
not deleted from its EntitySet, is merely unlinked from the entity
you were navigating from.</dd>
</dl>
<p>The following attribute is useful for consumers of the API (and should
be treated as read only)</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.entitySet" title="pyslet.odata2.csdl.EntityCollection.entitySet"><tt class="xref py py-attr docutils literal"><span class="pre">entitySet</span></tt></a></dt>
<dd>The <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet" title="pyslet.odata2.csdl.EntitySet"><tt class="xref py py-class docutils literal"><span class="pre">EntitySet</span></tt></a> of this collection. In
the case of a collection opened through navigation this is the base
entity set.</dd>
</dl>
<p>In addition to all the usual dictionary methods like <em>len</em>, <em>itervalues</em>
and so on, the following methods are useful for consumers of the API:</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.GetLocation" title="pyslet.odata2.csdl.EntityCollection.GetLocation"><tt class="xref py py-meth docutils literal"><span class="pre">GetLocation()</span></tt></a></dt>
<dd>Returns a <a class="reference internal" href="rfc2396.html#pyslet.rfc2396.URI" title="pyslet.rfc2396.URI"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.rfc2396.URI</span></tt></a> object that represents
this entity collection.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.GetTitle" title="pyslet.odata2.csdl.EntityCollection.GetTitle"><tt class="xref py py-meth docutils literal"><span class="pre">GetTitle()</span></tt></a></dt>
<dd>Returns a user-friendly title to represent this entity collection.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.NewEntity" title="pyslet.odata2.csdl.EntityCollection.NewEntity"><tt class="xref py py-meth docutils literal"><span class="pre">NewEntity()</span></tt></a></dt>
<dd>Creates a new entity suitable for inserting into this collection.
The entity does not exist until it is inserted with InsertEntity.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.CopyEntity" title="pyslet.odata2.csdl.EntityCollection.CopyEntity"><tt class="xref py py-meth docutils literal"><span class="pre">CopyEntity()</span></tt></a></dt>
<dd>Creates a new entity by copying all non-key properties from another
entity. The entity does not exist until it is inserted with
InsertEntity.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.InsertEntity" title="pyslet.odata2.csdl.EntityCollection.InsertEntity"><tt class="xref py py-meth docutils literal"><span class="pre">InsertEntity()</span></tt></a></dt>
<dd><p class="first">Inserts an entity previously created by NewEntity or CopyEntity.
When inserting an entity any active filter is ignored.</p>
<p>Warning: an active filter may result in a paradoxical KeyError:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">pyslet.odata2.core</span> <span class="kn">as</span> <span class="nn">core</span>
<span class="k">with</span> <span class="n">people</span><span class="o">.</span><span class="n">OpenCollection</span><span class="p">()</span> <span class="k">as</span> <span class="n">collection</span><span class="p">:</span>
        <span class="n">collection</span><span class="o">.</span><span class="n">Filter</span><span class="p">(</span><span class="n">core</span><span class="o">.</span><span class="n">CommonExpression</span><span class="o">.</span><span class="n">FromString</span><span class="p">(</span><span class="s">&quot;startswith(Name,&#39;D&#39;)&quot;</span><span class="p">))</span>
        <span class="n">newEntity</span><span class="o">=</span><span class="n">collection</span><span class="o">.</span><span class="n">NewEntity</span><span class="p">()</span>
        <span class="n">newEntity</span><span class="p">[</span><span class="s">&#39;Key&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
        <span class="n">newEntity</span><span class="p">[</span><span class="s">&#39;Name&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="s">u&quot;Steve&quot;</span><span class="p">)</span>
        <span class="n">collection</span><span class="o">.</span><span class="n">InsertEntity</span><span class="p">(</span><span class="n">newEntity</span><span class="p">)</span>
        <span class="c"># newEntity now exists in the base collection but...</span>
        <span class="n">e1</span><span class="o">=</span><span class="n">collection</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="c"># ...raises KeyError as newEntity did not match the filter!</span>
</pre></div>
</div>
<p class="last">It is recommended that collections used to insert entities are not
filtered.</p>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.UpdateEntity" title="pyslet.odata2.csdl.EntityCollection.UpdateEntity"><tt class="xref py py-meth docutils literal"><span class="pre">UpdateEntity()</span></tt></a></dt>
<dd>Updates an existing entity following changes to the Entity&#8217;s values.
You can&#8217;t update the values of key properties.  To change the key
you will need to create a new entity with CopyEntity, insert the new
entity and then remove the old one.  Like InsertEntity, the current
filter is ignored.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.SetPage" title="pyslet.odata2.csdl.EntityCollection.SetPage"><tt class="xref py py-meth docutils literal"><span class="pre">SetPage()</span></tt></a></dt>
<dd>Sets the top and skip values for this collection, equivalent to the
$top and $skip options in OData. This value only affects calls to
iterpage.  See <a class="reference internal" href="#paging">Paging</a> for more information.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.iterpage" title="pyslet.odata2.csdl.EntityCollection.iterpage"><tt class="xref py py-meth docutils literal"><span class="pre">iterpage()</span></tt></a></dt>
<dd>Iterates through a subset of the entities returned by itervalues
defined by the top and skip values.  See <a class="reference internal" href="#paging">Paging</a> for more
information.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.Filter" title="pyslet.odata2.csdl.EntityCollection.Filter"><tt class="xref py py-meth docutils literal"><span class="pre">Filter()</span></tt></a></dt>
<dd>Sets the filter for this collection, equivalent to the $filter
option in OData. Once set this value effects all future entities
returned from the collection (with the exception of NewEntity).  See
<a class="reference internal" href="#filtering-collections">Filtering Collections</a> for more information.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.OrderBy" title="pyslet.odata2.csdl.EntityCollection.OrderBy"><tt class="xref py py-meth docutils literal"><span class="pre">OrderBy()</span></tt></a></dt>
<dd>Sets the filter for this collection, equivalent to the $orderby
option in OData. Once set this value effects all future iterations
through the collection.  See <a class="reference internal" href="#ordering-collections">Ordering Collections</a> for more
information.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.Expand" title="pyslet.odata2.csdl.EntityCollection.Expand"><tt class="xref py py-meth docutils literal"><span class="pre">Expand()</span></tt></a></dt>
<dd>Sets expand and select options for this collection, equivalent to
the $expand and $select system query options in OData.  Once set
these values effect all future entities returned from the collection
(with the exception of NewEntity).  See <a class="reference internal" href="#expand-and-select">Expand and Select</a> for
more information.</dd>
</dl>
<div class="section" id="paging">
<h4>2.1.1.2.2.1. Paging<a class="headerlink" href="#paging" title="Permalink to this headline">¶</a></h4>
<p><em>Supported from build 0.4.20140215 onwards</em></p>
<p>The $top/$skip options in OData are a useful way to restrict the amount
of data that an OData server returns.  The collection dictionary always
behaves as if it contains all entities so the value returned by <em>len</em>
doesn&#8217;t change if you set top and skip values and nor does the set of
entities returned by itervalues and similar methods.</p>
<p>In most cases, the server will impose a reasonable maximum on each
request using server-enforced paging.  However, you may wish to set a
smaller <em>top</em> value or simply have more control over the automatic
paging implemented by the default iterators.</p>
<p>To iterate through a single page of entities you&#8217;ll start by using the
the <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.SetPage" title="pyslet.odata2.csdl.EntityCollection.SetPage"><tt class="xref py py-meth docutils literal"><span class="pre">SetPage()</span></tt></a> method to
specify values for top and, optinally, skip.  You must then use the
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.iterpage" title="pyslet.odata2.csdl.EntityCollection.iterpage"><tt class="xref py py-meth docutils literal"><span class="pre">iterpage()</span></tt></a> method to
iterate through the entities in just that page.  The <em>setNextPage</em>
boolean parameter indicates whether or not the next call to iterpage
iterates over the same page or the next page of the collection.</p>
<p>To continue the example above, in which <em>products</em> is an open collection
from the Northwind data service:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">SetPage</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">50</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">iterpage</span><span class="p">(</span><span class="bp">True</span><span class="p">):</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$skip=50&amp;$top=5 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">51 Manjimup Dried Apples</span>
<span class="go">52 Filo Mix</span>
<span class="go">53 Perth Pasties</span>
<span class="go">54 Tourtière</span>
<span class="go">55 Pâté chinois</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">iterpage</span><span class="p">(</span><span class="bp">True</span><span class="p">):</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$skip=55&amp;$top=5 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">56 Gnocchi di nonna Alice</span>
<span class="go">57 Ravioli Angelo</span>
<span class="go">58 Escargots de Bourgogne</span>
<span class="go">59 Raclette Courdavault</span>
<span class="go">60 Camembert Pierrot</span>
</pre></div>
</div>
<p>In some cases, the server will restrict the page size and fewer entities
will be returned than expected, in these cases the skiptoken is used
automatically when the next page is requested:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">SetPage</span><span class="p">(</span><span class="mi">30</span><span class="p">,</span><span class="mi">50</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">iterpage</span><span class="p">(</span><span class="bp">True</span><span class="p">):</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$skip=50&amp;$top=30 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">51 Manjimup Dried Apples</span>
<span class="go">52 Filo Mix</span>
<span class="go">53 Perth Pasties</span>
<span class="gp">... </span><span class="p">[</span><span class="ow">and</span> <span class="n">so</span> <span class="n">on</span><span class="p">]</span>
<span class="gp">...</span>
<span class="go">69 Gudbrandsdalsost</span>
<span class="go">70 Outback Lager</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">iterpage</span><span class="p">(</span><span class="bp">True</span><span class="p">):</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$top=30&amp;$skiptoken=70 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">71 Flotemysost</span>
<span class="go">72 Mozzarella di Giovanni</span>
<span class="go">73 Röd Kaviar</span>
<span class="go">74 Longlife Tofu</span>
<span class="go">75 Rhönbräu Klosterbier</span>
<span class="go">76 Lakkalikööri</span>
<span class="go">77 Original Frankfurter grüne Soße</span>
</pre></div>
</div>
</div>
<div class="section" id="filtering-collections">
<h4>2.1.1.2.2.2. Filtering Collections<a class="headerlink" href="#filtering-collections" title="Permalink to this headline">¶</a></h4>
<p>By default, an entity collection contains all items in the entity set
or, if the collection was obtained by navigation, all items linked to
the entity by the property being navigated.  Filtering a collection
(potentially) selects a sub-set of the these entities based on a filter
expression.</p>
<p>Filter expressions are set using the
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.Filter" title="pyslet.odata2.csdl.EntityCollection.Filter"><tt class="xref py py-meth docutils literal"><span class="pre">Filter()</span></tt></a> method of the
collection.  Once a filter is set, the dictionary methods, and iterpage,
will only return entities that match the filter.</p>
<p>The easiest way to set a filter is to compile one directly from a string
representation using OData&#8217;s query language.  For example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">pyslet.odata2.core</span> <span class="kn">as</span> <span class="nn">core</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">filter</span><span class="o">=</span><span class="n">core</span><span class="o">.</span><span class="n">CommonExpression</span><span class="o">.</span><span class="n">FromString</span><span class="p">(</span><span class="s">&quot;substringof(&#39;one&#39;,ProductName)&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Filter</span><span class="p">(</span><span class="nb">filter</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">itervalues</span><span class="p">():</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$filter=substringof(&#39;one&#39;%2CProductName) HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">21 Sir Rodney&#39;s Scones</span>
<span class="go">32 Mascarpone Fabioli</span>
</pre></div>
</div>
<p>To remove a filter, set the filter expression to None:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Filter</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="ordering-collections">
<h4>2.1.1.2.2.3. Ordering Collections<a class="headerlink" href="#ordering-collections" title="Permalink to this headline">¶</a></h4>
<p>Like OData and python dictionaries, this API does not specify a default
order in which entities will be returned by the iterators.  However,
unlike python dictionaries you can control this order using an orderby
option.</p>
<p>OrderBy expressions are set using the
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection.OrderBy" title="pyslet.odata2.csdl.EntityCollection.OrderBy"><tt class="xref py py-meth docutils literal"><span class="pre">OrderBy()</span></tt></a> method of the
collection.  Once an order by expression is set, the dictionary methods,
and iterpage, will return entities in the order specified.</p>
<p>The easiest way to define an ordering is to compile one directly from a
string representation using OData&#8217;s query language.  For example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">ordering</span><span class="o">=</span><span class="n">core</span><span class="o">.</span><span class="n">CommonExpression</span><span class="o">.</span><span class="n">OrderByFromString</span><span class="p">(</span><span class="s">&quot;ProductName desc&quot;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">OrderBy</span><span class="p">(</span><span class="n">ordering</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">products</span><span class="o">.</span><span class="n">itervalues</span><span class="p">():</span> <span class="k">print</span> <span class="n">p</span><span class="o">.</span><span class="n">Key</span><span class="p">(),</span> <span class="n">p</span><span class="p">[</span><span class="s">&#39;ProductName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$orderby=ProductName%20desc HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">47 Zaanse koeken</span>
<span class="go">64 Wimmers gute Semmelknödel</span>
<span class="go">63 Vegie-spread</span>
<span class="go">50 Valkoinen suklaa</span>
<span class="go">7 Uncle Bob&#39;s Organic Dried Pears</span>
<span class="go">23 Tunnbröd</span>
<span class="gp">... </span><span class="p">[</span><span class="ow">and</span> <span class="n">so</span> <span class="n">on</span><span class="p">]</span>
<span class="gp">...</span>
<span class="go">56 Gnocchi di nonna Alice</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products?$orderby=ProductName%20desc&amp;$skiptoken=&#39;Gnocchi%20di%20nonna%20Alice&#39;,56 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">15 Genen Shouyu</span>
<span class="go">33 Geitost</span>
<span class="go">71 Flotemysost</span>
<span class="gp">... </span><span class="p">[</span><span class="ow">and</span> <span class="n">so</span> <span class="n">on</span><span class="p">]</span>
<span class="gp">...</span>
<span class="go">40 Boston Crab Meat</span>
<span class="go">3 Aniseed Syrup</span>
<span class="go">17 Alice Mutton</span>
</pre></div>
</div>
<p>To remove an ordering, set the orderby expression to None:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Orderby</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class="section" id="expand-and-select">
<h4>2.1.1.2.2.4. Expand and Select<a class="headerlink" href="#expand-and-select" title="Permalink to this headline">¶</a></h4>
<p>Expansion and selection are two interrelated concepts in the API.
Expansion allows you to follow specified navigation properties
retrieving the entities they link to in the same way that simple and
complex property values are retrieved.</p>
<p>Expand options are represented by nested dictionaries of strings.  For
example, to expand the Supplier navigation property of Products you
would use a dictionary like this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">expansion</span><span class="o">=</span><span class="p">{</span><span class="s">&#39;Supplier&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">}</span>
</pre></div>
</div>
<p>The value in the dictionary is either None, indicating no further
expansion, or another dictionary specifying the expansion to apply to
any linked Suppliers:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Expand</span><span class="p">({</span><span class="s">&#39;Supplier&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">},</span><span class="bp">None</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scones</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)?$expand=Supplier HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">supplier</span><span class="o">=</span><span class="n">scones</span><span class="p">[</span><span class="s">&#39;Supplier&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">GetEntity</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">supplier</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">SupplierID 8</span>
<span class="go">CompanyName Specialty Biscuits, Ltd.</span>
<span class="go">ContactName Peter Wilson</span>
<span class="go">ContactTitle Sales Representative</span>
<span class="go">Address 29 King&#39;s Way</span>
<span class="go">City Manchester</span>
<span class="go">Region None</span>
<span class="go">PostalCode M14 GSD</span>
<span class="go">Country UK</span>
<span class="go">Phone (161) 555-4448</span>
<span class="go">Fax None</span>
<span class="go">HomePage None</span>
</pre></div>
</div>
<p>A critical point to note is that applying an expansion to a collection
means that linked entities are retrieved at the same time as the entity
they are linked to and cached.  In the example above, the GetEntity call
does not generate a call to the server.  Compare this with the same code
executed without the expansion:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Expand</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span><span class="bp">None</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scones</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21) HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">supplier</span><span class="o">=</span><span class="n">scones</span><span class="p">[</span><span class="s">&#39;Supplier&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">GetEntity</span><span class="p">()</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)/Supplier HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
</pre></div>
</div>
<p>The select option complements expansion, narrowing down the simple and
complex properties that are retrieved from the data source.  You specify
a select option in a similar way, using nested dictionaries.  Simple and
complex properties must always map to None, for a more complex example
with navigation properties see below.  Suppose we are only interested in
the product name:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Expand</span><span class="p">(</span><span class="bp">None</span><span class="p">,{</span><span class="s">&#39;ProductName&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scones</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)?$select=ProductID%2CProductName HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">scones</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">ProductID 21</span>
<span class="go">ProductName Sir Rodney&#39;s Scones</span>
<span class="go">SupplierID None</span>
<span class="go">CategoryID None</span>
<span class="go">QuantityPerUnit None</span>
<span class="go">UnitPrice None</span>
<span class="go">UnitsInStock None</span>
<span class="go">UnitsOnOrder None</span>
<span class="go">ReorderLevel None</span>
<span class="go">Discontinued None</span>
</pre></div>
</div>
<p>In Pyslet, the values of the key properties are <em>always</em> retrieved, even
if they are not selected.  This is required to maintain the
dictionary-like behaviour of the collection.  An entity retrieved this
way has NULL values for any properties that weren&#8217;t retrieved.  The
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.Selected" title="pyslet.odata2.csdl.Entity.Selected"><tt class="xref py py-meth docutils literal"><span class="pre">Selected()</span></tt></a> method allows you to
determine if a value is NULL in the data source or NULL because it is
not selected:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">scones</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">scones</span><span class="o">.</span><span class="n">Selected</span><span class="p">(</span><span class="n">k</span><span class="p">):</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">ProductID 21</span>
<span class="go">ProductName Sir Rodney&#39;s Scones</span>
</pre></div>
</div>
<p>The expand and select options can be combined in complex ways:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">products</span><span class="o">.</span><span class="n">Expand</span><span class="p">({</span><span class="s">&#39;Supplier&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">},{</span><span class="s">&#39;ProductName&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">,</span><span class="s">&#39;Supplier&#39;</span><span class="p">:{</span><span class="s">&#39;Phone&#39;</span><span class="p">:</span><span class="bp">None</span><span class="p">}})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">scones</span><span class="o">=</span><span class="n">products</span><span class="p">[</span><span class="mi">21</span><span class="p">]</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)?$expand=Supplier&amp;$select=ProductID%2CProductName%2CSupplier%2FPhone%2CSupplier%2FSupplierID HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">supplier</span><span class="o">=</span><span class="n">scones</span><span class="p">[</span><span class="s">&#39;Supplier&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">GetEntity</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">scones</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">scones</span><span class="o">.</span><span class="n">Selected</span><span class="p">(</span><span class="n">k</span><span class="p">):</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">ProductID 21</span>
<span class="go">ProductName Sir Rodney&#39;s Scones</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span> <span class="ow">in</span> <span class="n">supplier</span><span class="o">.</span><span class="n">DataItems</span><span class="p">():</span>
<span class="gp">... </span> <span class="k">if</span> <span class="n">supplier</span><span class="o">.</span><span class="n">Selected</span><span class="p">(</span><span class="n">k</span><span class="p">):</span> <span class="k">print</span> <span class="n">k</span><span class="p">,</span><span class="n">v</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">SupplierID 8</span>
<span class="go">Phone (161) 555-4448</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="entity-objects">
<h3>2.1.1.2.3. Entity Objects<a class="headerlink" href="#entity-objects" title="Permalink to this headline">¶</a></h3>
<p>Continuing further with the database analogy and
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity" title="pyslet.odata2.csdl.Entity"><tt class="xref py py-class docutils literal"><span class="pre">Entity</span></tt></a> is like a single record.</p>
<p>Entity instances behave like a read-only dictionary mapping property
names onto their values.  The values are either <a class="reference internal" href="#simplevalue">SimpleValue</a>, <a class="reference internal" href="#complex">Complex</a>
or <a class="reference internal" href="#deferredvalue">DeferredValue</a> instances.  All property values are created on
construction and cannot be assigned.  To update a SimpleValue, whether
it is a direct child or part of a Complex value, use its
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetFromValue" title="pyslet.odata2.csdl.SimpleValue.SetFromValue"><tt class="xref py py-meth docutils literal"><span class="pre">SetFromValue()</span></tt></a> method:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">entity</span><span class="p">[</span><span class="s">&#39;Name&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="s">&quot;Steve&quot;</span><span class="p">)</span>
<span class="n">entity</span><span class="p">[</span><span class="s">&#39;Address&#39;</span><span class="p">][</span><span class="s">&#39;City&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="s">&quot;Cambridge&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>The following attributes are useful for consumers of the API (and should
be treated as read only):</p>
<dl class="docutils">
<dt><tt class="xref py py-attr docutils literal"><span class="pre">entitySet</span></tt></dt>
<dd>The <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntitySet" title="pyslet.odata2.csdl.EntitySet"><tt class="xref py py-class docutils literal"><span class="pre">EntitySet</span></tt></a> to which this entity
belongs.</dd>
<dt><tt class="xref py py-attr docutils literal"><span class="pre">typeDef</span></tt></dt>
<dd>The <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityType" title="pyslet.odata2.csdl.EntityType"><tt class="xref py py-class docutils literal"><span class="pre">EntityType</span></tt></a> which defines this
entity&#8217;s type.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.exists" title="pyslet.odata2.csdl.Entity.exists"><tt class="xref py py-attr docutils literal"><span class="pre">exists</span></tt></a></dt>
<dd>True if this entity exists in the collection, i.e., it was returned
by one of the dictionary methods of an entity collection such as
<em>itervalues</em> or [key] look-up.</dd>
</dl>
<p>The following methods are useful for consumers of the API:</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.Key" title="pyslet.odata2.csdl.Entity.Key"><tt class="xref py py-meth docutils literal"><span class="pre">Key()</span></tt></a></dt>
<dd>Returns the entity&#8217;s key, as a single python value or tuple in the
case of compound keys</dd>
<dt><tt class="xref py py-meth docutils literal"><span class="pre">GetLocation()</span></tt></dt>
<dd><p class="first">Returns a <a class="reference internal" href="rfc2396.html#pyslet.rfc2396.URI" title="pyslet.rfc2396.URI"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.rfc2396.URI</span></tt></a> object that represents this
entity:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">scones</span><span class="o">.</span><span class="n">GetLocation</span><span class="p">()</span>
<span class="go">http://services.odata.org/V2/Northwind/Northwind.svc/Products(21)</span>
</pre></div>
</div>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.DataKeys" title="pyslet.odata2.csdl.Entity.DataKeys"><tt class="xref py py-meth docutils literal"><span class="pre">DataKeys()</span></tt></a></dt>
<dd><p class="first">Iterates over the simple and complex property names:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">scones</span><span class="o">.</span><span class="n">DataKeys</span><span class="p">())</span>
<span class="go">[u&#39;ProductID&#39;, u&#39;ProductName&#39;, u&#39;SupplierID&#39;, u&#39;CategoryID&#39;, u&#39;QuantityPerUnit&#39;, u&#39;UnitPrice&#39;, u&#39;UnitsInStock&#39;, u&#39;UnitsOnOrder&#39;, u&#39;ReorderLevel&#39;, u&#39;Discontinued&#39;]</span>
</pre></div>
</div>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.DataItems" title="pyslet.odata2.csdl.Entity.DataItems"><tt class="xref py py-meth docutils literal"><span class="pre">DataItems()</span></tt></a></dt>
<dd>Iterates over tuples of simple and complex property (name,value)
pairs. See above for examples of usage.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.Selected" title="pyslet.odata2.csdl.Entity.Selected"><tt class="xref py py-meth docutils literal"><span class="pre">Selected()</span></tt></a></dt>
<dd>Tests if the given data property is selected.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.NavigationKeys" title="pyslet.odata2.csdl.Entity.NavigationKeys"><tt class="xref py py-meth docutils literal"><span class="pre">NavigationKeys()</span></tt></a></dt>
<dd><p class="first">Iterates over the navigation property names:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="nb">list</span><span class="p">(</span><span class="n">scones</span><span class="o">.</span><span class="n">NavigationKeys</span><span class="p">())</span>
<span class="go">[u&#39;Category&#39;, u&#39;Order_Details&#39;, u&#39;Supplier&#39;]</span>
</pre></div>
</div>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.NavigationItems" title="pyslet.odata2.csdl.Entity.NavigationItems"><tt class="xref py py-meth docutils literal"><span class="pre">NavigationItems()</span></tt></a></dt>
<dd>Iterates over tuples of navigation property (name,DeferredValue)
pairs.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.IsNavigationProperty" title="pyslet.odata2.csdl.Entity.IsNavigationProperty"><tt class="xref py py-meth docutils literal"><span class="pre">IsNavigationProperty()</span></tt></a></dt>
<dd>Tests if a navigation property with the given name exists</dd>
</dl>
<p>The following methods can be used only on entities that exists, i.e.,
entities that have been returned from one of the collection&#8217;s dictionary
methods:</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.Update" title="pyslet.odata2.csdl.Entity.Update"><tt class="xref py py-meth docutils literal"><span class="pre">Update()</span></tt></a></dt>
<dd>Normally you&#8217;ll use the the Update method of an open
EntityCollection but in cases where the originating collection is no
longer open this method can be used as a convenience method for
opening the base collection, updating the entity and then closing
the collection collection again.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.Delete" title="pyslet.odata2.csdl.Entity.Delete"><tt class="xref py py-meth docutils literal"><span class="pre">Delete()</span></tt></a></dt>
<dd>Deletes this entity from the base entity set.  If you already have
the base entity set open it is more efficient to use the <em>del</em>
operator but if the collection is no longer open or the entity was
obtained from a collection opened through navigation then this
method can be used to delete the entity.</dd>
</dl>
<p>The following method can only be used on entities that don&#8217;t exist,
i.e., entities returned from the collection&#8217;s NewEntity or CopyEntity
methods that have not been inserted.</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.Entity.SetKey" title="pyslet.odata2.csdl.Entity.SetKey"><tt class="xref py py-meth docutils literal"><span class="pre">SetKey()</span></tt></a></dt>
<dd>Sets the entity&#8217;s key</dd>
</dl>
<div class="section" id="simplevalue">
<h4>2.1.1.2.3.1. SimpleValue<a class="headerlink" href="#simplevalue" title="Permalink to this headline">¶</a></h4>
<p>Simple property values are represented by (sub-classes of)
<a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue" title="pyslet.odata2.csdl.SimpleValue"><tt class="xref py py-class docutils literal"><span class="pre">SimpleValue</span></tt></a>, they share a number of
common methods:</p>
<dl class="docutils">
<dt><tt class="xref py py-meth docutils literal"><span class="pre">IsNull()</span></tt></dt>
<dd><p class="first">Returns True if this value is NULL.  This method is also used
by Python&#8217;s non-zero test so:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="n">entity</span><span class="p">[</span><span class="s">&#39;Property&#39;</span><span class="p">]:</span>
        <span class="k">print</span> <span class="n">entity</span><span class="p">[</span><span class="s">&#39;Property&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
        <span class="c"># prints even if value is 0</span>
</pre></div>
</div>
<p>will print the Property value of entity if it is non-NULL.  In
particular, it will print empty strings or other representations of
zero.  If you want to exclude these from the test you should test
the value attribute directly:</p>
<div class="last highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="n">entity</span><span class="p">[</span><span class="s">&#39;Property&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="p">:</span>
        <span class="k">print</span> <span class="n">entity</span><span class="p">[</span><span class="s">&#39;Property&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
        <span class="c"># will not print if value is 0</span>
</pre></div>
</div>
</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetFromValue" title="pyslet.odata2.csdl.SimpleValue.SetFromValue"><tt class="xref py py-meth docutils literal"><span class="pre">SetFromValue()</span></tt></a></dt>
<dd>Updates the value, coercing the argument to the correct type and
range checking its value.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetFromSimpleValue" title="pyslet.odata2.csdl.SimpleValue.SetFromSimpleValue"><tt class="xref py py-meth docutils literal"><span class="pre">SetFromSimpleValue()</span></tt></a></dt>
<dd>Updates the value from another SimpleValue, if the types match then
the value is simply copied, otherwise the value is coerced using
SetFromValue.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetFromLiteral" title="pyslet.odata2.csdl.SimpleValue.SetFromLiteral"><tt class="xref py py-meth docutils literal"><span class="pre">SetFromLiteral()</span></tt></a></dt>
<dd>Updates the value by parsing it from a (unicode) string.  This is
the opposite to the unicode function.  The literal form is the form
used when serializing the value to XML (but does not include XML
character escaping).</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetNull" title="pyslet.odata2.csdl.SimpleValue.SetNull"><tt class="xref py py-meth docutils literal"><span class="pre">SetNull()</span></tt></a></dt>
<dd>Updates the value to NULL</dd>
</dl>
<p>The value attribute is always an immutable value in python and so can be
used as a key in your own dictionaries.  The following list describes
the mapping from the EDM-defined simple types to their corresponding
native Python types.</p>
<dl class="docutils">
<dt>Edm.Boolean:</dt>
<dd>one of the Python constants True or False</dd>
<dt>Edm.Byte, Edm.SByte, Edm.Int16, Edm.Int32:</dt>
<dd>int</dd>
<dt>Edm.Int64:</dt>
<dd>long</dd>
<dt>Edm.Double, Edm.Single:</dt>
<dd>python float</dd>
<dt>Edm.Decimal:</dt>
<dd>python Decimal instance (from the built-in decimal module)</dd>
<dt>Edm.DateTime, Edm.DateTimeOffset:</dt>
<dd><p class="first">py:class:<cite>pyslet.iso8601.TimePoint</cite> instance</p>
<p class="last">This is a custom object in Pyslet, see <a class="reference internal" href="#working-with-dates">Working with Dates</a> for
more information.</p>
</dd>
<dt>Edm.Time:</dt>
<dd><p class="first">py:class:<cite>pyslet.iso8601.Time</cite> instance</p>
<p>Early versions of the OData specification incorrectly mapped this
type to the XML Schema duration.  The use of a Time object to
represent it, rather than a duration, reflects this correction.</p>
<p class="last">See <a class="reference internal" href="#working-with-dates">Working with Dates</a> for more information.</p>
</dd>
<dt>Edm.Binary:</dt>
<dd>raw string</dd>
<dt>Edm.String:</dt>
<dd>unicode string</dd>
<dt>Edm.Guid:</dt>
<dd>Python UUID instance (from the built-in uuid module)</dd>
</dl>
</div>
<div class="section" id="complex">
<h4>2.1.1.2.3.2. Complex<a class="headerlink" href="#complex" title="Permalink to this headline">¶</a></h4>
<p>Complex values behave like dictionaries of data properties.  They do not
have keys or navigation properties.  They are never NULL, IsNull and the
Python non-zero test will always return True.</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.SimpleValue.SetNull" title="pyslet.odata2.csdl.SimpleValue.SetNull"><tt class="xref py py-meth docutils literal"><span class="pre">SetNull()</span></tt></a></dt>
<dd>Although a Complex value can never be NULL, this method will set all
of its data properties (recursively if necessary) to NULL</dd>
</dl>
</div>
<div class="section" id="deferredvalue">
<h4>2.1.1.2.3.3. DeferredValue<a class="headerlink" href="#deferredvalue" title="Permalink to this headline">¶</a></h4>
<p>Navigation properties are represented as <tt class="xref py py-class docutils literal"><span class="pre">DeferredValue</span></tt>
instances.  All deferred values can be treated as an entity collection
and opened in a similar way to an entity set:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">sconeSuppliers</span><span class="o">=</span><span class="n">scones</span><span class="p">[</span><span class="s">&#39;Supplier&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">OpenCollection</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">sconeSuppliers</span><span class="o">.</span><span class="n">itervalues</span><span class="p">():</span> <span class="k">print</span> <span class="n">s</span><span class="p">[</span><span class="s">&#39;CompanyName&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="gp">...</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Products(21)/Supplier HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="go">Specialty Biscuits, Ltd.</span>
<span class="go">&gt;&gt;&gt;</span>
</pre></div>
</div>
<p>For reading, a collection opened from a deferred value behaves in
exactly the same way as a collection opened from a base entity set.
However, for writing there are some difference described above in
<a class="reference internal" href="#entity-collections">Entity Collections</a>.</p>
<p>If you use the dictionary methods to update the collection the changes
are made straight away by accessing the data source directly.  If you
want to make a number of changes simultaneously, or you want to link
entities to entities that don&#8217;t yet exist, then you should use the
BindEntity method described below instead.  This method defers the
changes until the parent entity is updated (or inserted, in the case of
non-existent entities.)</p>
<p>Read-only attributes useful to data consumers:</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.name" title="pyslet.odata2.csdl.DeferredValue.name"><tt class="xref py py-attr docutils literal"><span class="pre">name</span></tt></a></dt>
<dd>The name of the navigation property</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.fromEntity" title="pyslet.odata2.csdl.DeferredValue.fromEntity"><tt class="xref py py-attr docutils literal"><span class="pre">fromEntity</span></tt></a></dt>
<dd>The parent entity of this navigation property</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.pDef" title="pyslet.odata2.csdl.DeferredValue.pDef"><tt class="xref py py-attr docutils literal"><span class="pre">pDef</span></tt></a></dt>
<dd>The <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.NavigationProperty" title="pyslet.odata2.csdl.NavigationProperty"><tt class="xref py py-class docutils literal"><span class="pre">NavigationProperty</span></tt></a> that defines
this navigation property in the model.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.isRequired" title="pyslet.odata2.csdl.DeferredValue.isRequired"><tt class="xref py py-attr docutils literal"><span class="pre">isRequired</span></tt></a></dt>
<dd>True if the target of this property has multiplicity 1, i.e., it is
required.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.isCollection" title="pyslet.odata2.csdl.DeferredValue.isCollection"><tt class="xref py py-attr docutils literal"><span class="pre">isCollection</span></tt></a></dt>
<dd>True if the target of this property has multiplicity *</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.isExpanded" title="pyslet.odata2.csdl.DeferredValue.isExpanded"><tt class="xref py py-attr docutils literal"><span class="pre">isExpanded</span></tt></a></dt>
<dd>True if this navigation property has been expanded.  Expanded
navigation keep a cached version of the target collection.  Although
you can open it and use it in the same way any other collection the
values returned are returned from the cache and not by accessing the
data source.</dd>
</dl>
<p>Methods useful to data consumers:</p>
<dl class="docutils">
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.OpenCollection" title="pyslet.odata2.csdl.DeferredValue.OpenCollection"><tt class="xref py py-meth docutils literal"><span class="pre">OpenCollection()</span></tt></a></dt>
<dd>Returns an <a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.EntityCollection" title="pyslet.odata2.csdl.EntityCollection"><tt class="xref py py-class docutils literal"><span class="pre">pyslet.odata2.csdl.EntityCollection</span></tt></a> object
that can be used to access the target entities.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.GetEntity" title="pyslet.odata2.csdl.DeferredValue.GetEntity"><tt class="xref py py-meth docutils literal"><span class="pre">GetEntity()</span></tt></a></dt>
<dd>Convenience method that returns the entity that is the target of the
link when the target has multiplicity 1 or 0..1.  If no entity is
linked by the association then None is returned.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.BindEntity" title="pyslet.odata2.csdl.DeferredValue.BindEntity"><tt class="xref py py-meth docutils literal"><span class="pre">BindEntity()</span></tt></a></dt>
<dd>Marks the target entity for addition to this navigation collection
on next update or insert.  If this navigation property is not a
collection then the target entity will replace any existing target
of the link.</dd>
<dt><a class="reference internal" href="odatav2_csdl.html#pyslet.odata2.csdl.DeferredValue.Target" title="pyslet.odata2.csdl.DeferredValue.Target"><tt class="xref py py-meth docutils literal"><span class="pre">Target()</span></tt></a></dt>
<dd>The target entity set of this navigation property.</dd>
</dl>
</div>
<div class="section" id="working-with-dates">
<h4>2.1.1.2.3.4. Working with Dates<a class="headerlink" href="#working-with-dates" title="Permalink to this headline">¶</a></h4>
<p>In the EDM there are two types of date, DateTime and DateTimeOffset.
The first represents a time-point in an implicit zone and the second
represents a time-point with the zone offset explicitly set.</p>
<p>Both types are represented by the custom :py:class:pyslet.iso8601.TimePoint`
class in Pyslet.</p>
<p><em>time module from build 0.4.20140217 onwards</em></p>
<p>Interacting with Python&#8217;s time module is done using the struct_time type,
or lists that have values corresponding to those in struct_time:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">time</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">orders</span><span class="o">=</span><span class="n">c</span><span class="o">.</span><span class="n">feeds</span><span class="p">[</span><span class="s">&#39;Orders&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">OpenCollection</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">orders</span><span class="o">.</span><span class="n">SetPage</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">top</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">orders</span><span class="o">.</span><span class="n">iterpage</span><span class="p">())</span>
<span class="go">INFO:root:Sending request to services.odata.org</span>
<span class="go">INFO:root:GET /V2/Northwind/Northwind.svc/Orders?$skip=0&amp;$top=5 HTTP/1.1</span>
<span class="go">INFO:root:Finished Response, status 200</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="go">1996-07-04T00:00:00</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span><span class="o">=</span><span class="p">[</span><span class="bp">None</span><span class="p">]</span><span class="o">*</span><span class="mi">9</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">UpdateStructTime</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span>
<span class="go">[1996, 7, 4, 0, 0, 0, 3, 186, -1]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%a, </span><span class="si">%d</span><span class="s"> %b %Y %H:%M:%S&quot;</span><span class="p">,</span><span class="n">t</span><span class="p">)</span>
<span class="go">&#39;Thu, 04 Jul 1996 00:00:00&#39;</span>
</pre></div>
</div>
<p>You can set values obtained from the time module in a similar way:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">pyslet.iso8601</span> <span class="kn">as</span> <span class="nn">iso</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">t</span><span class="o">=</span><span class="n">time</span><span class="o">.</span><span class="n">gmtime</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="n">iso</span><span class="o">.</span><span class="n">TimePoint</span><span class="o">.</span><span class="n">FromStructTime</span><span class="p">(</span><span class="n">t</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="go">2014-02-17T21:51:41</span>
</pre></div>
</div>
<p>But if you just want a timestamp use one of the built-in factory
methods:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="gp">&gt;&gt;&gt; </span><span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">SetFromValue</span><span class="p">(</span><span class="n">iso</span><span class="o">.</span><span class="n">TimePoint</span><span class="o">.</span><span class="n">FromNowUTC</span><span class="p">())</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">print</span> <span class="n">top</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">&#39;OrderDate&#39;</span><span class="p">]</span><span class="o">.</span><span class="n">value</span>
<span class="go">2014-02-17T21:56:23</span>
</pre></div>
</div>
<p>In future versions, look out for better support for datetime and
calendar module conversion methods.</p>
</div>
</div>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">2.1.1. Data Consumers</a><ul>
<li><a class="reference internal" href="#introduction">2.1.1.1. Introduction</a></li>
<li><a class="reference internal" href="#the-data-access-layer-in-depth">2.1.1.2. The Data Access Layer in Depth</a><ul>
<li><a class="reference internal" href="#entity-sets">2.1.1.2.1. Entity Sets</a></li>
<li><a class="reference internal" href="#entity-collections">2.1.1.2.2. Entity Collections</a><ul>
<li><a class="reference internal" href="#paging">2.1.1.2.2.1. Paging</a></li>
<li><a class="reference internal" href="#filtering-collections">2.1.1.2.2.2. Filtering Collections</a></li>
<li><a class="reference internal" href="#ordering-collections">2.1.1.2.2.3. Ordering Collections</a></li>
<li><a class="reference internal" href="#expand-and-select">2.1.1.2.2.4. Expand and Select</a></li>
</ul>
</li>
<li><a class="reference internal" href="#entity-objects">2.1.1.2.3. Entity Objects</a><ul>
<li><a class="reference internal" href="#simplevalue">2.1.1.2.3.1. SimpleValue</a></li>
<li><a class="reference internal" href="#complex">2.1.1.2.3.2. Complex</a></li>
<li><a class="reference internal" href="#deferredvalue">2.1.1.2.3.3. DeferredValue</a></li>
<li><a class="reference internal" href="#working-with-dates">2.1.1.2.3.4. Working with Dates</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>

  <h4>Previous topic</h4>
  <p class="topless"><a href="odatav2.html"
                        title="previous chapter">2.1. The Open Data Protocol (OData)</a></p>
  <h4>Next topic</h4>
  <p class="topless"><a href="odatav2_provider.html"
                        title="next chapter">2.1.2. OData Providers</a></p>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/odatav2_consumer.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="odatav2_provider.html" title="2.1.2. OData Providers"
             >next</a> |</li>
        <li class="right" >
          <a href="odatav2.html" title="2.1. The Open Data Protocol (OData)"
             >previous</a> |</li>
        <li><a href="index.html">Pyslet 0.4.20140526 documentation</a> &raquo;</li>
          <li><a href="general.html" >2. Supporting Standards</a> &raquo;</li>
          <li><a href="odatav2.html" >2.1. The Open Data Protocol (OData)</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
        &copy; Copyright ©2008-2014, Steve Lay.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.1.
    </div>
  </body>
</html>